﻿using Abp.Domain.Repositories;
using Abp.ObjectMapping;
using Abp.Runtime.Caching;
using AVIS.OutBound.Cities.Cache;
using AVIS.OutBound.Cities.Dto;
using AVIS.OutBound.Continents;
using AVIS.OutBound.EntityFramework.Models;
using AVIS.OutBound.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AVIS.OutBound.Cities
{
    /// <summary>
    /// 城市的应用服务类
    /// </summary>
    public class CityAppService : OutBoundAppServiceBase, ICityAppService
    {
        #region 构造函数
        private readonly ICityManager _cityManager;
        private readonly IRepository<City> _cityRepository;
        private readonly IRepository<AvisORRegion> _regionRepository;
        private readonly IRepository<Continent> _continentRepository;
        private readonly IRegionManager _regionManager;
        private readonly ICacheManager _cacheManager;
        private readonly IObjectMapper _objectMapper;

        public CityAppService(
            ICacheManager cacheManager,
            ICityManager cityManager,
            IObjectMapper objectMapper,
            IRepository<City> cityRepository,
            IRepository<AvisORRegion> regionRepository,
            IRepository<Continent> continentRepository,
            IRegionManager regionManager)
        {

            _cacheManager = cacheManager;
            _cityManager = cityManager;
            _cityRepository = cityRepository;
            _regionRepository = regionRepository;
            _continentRepository = continentRepository;
            _regionManager = regionManager;
            _objectMapper = objectMapper;
        }
        #endregion

        /// <summary>
        /// 获取热门城市
        /// </summary>
        /// <returns></returns>
        public IList<HotCityGroupDto> GetHotCity()
        {
            List<HotCityGroupDto> list = new List<HotCityGroupDto>();

            // 1. 获取所有的热门城市
            var hotCities = _cityManager.GetHotCity();

            // 2. 设置洲信息
            var dic = GetRegionAndContinent(hotCities.Select(c => c.RegionCode).ToArray());
            var dtoList = hotCities.Select(c =>
            {
                var dto = _objectMapper.Map<HotCityDto>(c);
                dto.CNSinple = dto.CNName.Length > 5 ? dto.CNName.Substring(0, 5) + "..." : dto.CNName;
                var item = dic[c.RegionCode];
                if (item != null)
                {
                    dto.ContinentSeqNo = item.ASOrder;
                    dto.ContinentASCNName = item.ASCNName;
                }
                return dto;
            });

            // 3. 国际热门城市
            list.Add(new HotCityGroupDto { ContinentName = "国际热门", list = dtoList.Where(c => c.IsHot).ToList() });

            // 4. 各大洲的热门城市
            var ContinentCNNames = dtoList.OrderBy(c => c.ContinentSeqNo).Select(c => c.ContinentASCNName).Distinct();
            foreach (var ContinentCNName in ContinentCNNames)
            {
                list.Add(new HotCityGroupDto
                {
                    ContinentName = ContinentCNName,
                    list = dtoList.Where(c => c.ContinentASCNName == ContinentCNName).ToList()
                });
            }

            return list;
        }

        /// <summary>
        /// 搜索城市信息
        /// </summary>
        /// <param name="k">关键字，按中英名称或中文拼音进行查询</param>
        /// <returns></returns>
        public IList<CityDto> QueryCity(string k)
        {
            var key = k.Trim();
            var query = from c in _cityRepository.GetAll()
                        where c.CNName.Contains(key) || c.ENName.Contains(key) || c.CNPY.Contains(key)
                        orderby c.RegionCode, c.CNName
                        select c;

            // 需要考虑：数据库三条数据导致前台显示三个曼谷目前用Distinct筛选掉重复的 但是具体待定！
            return _objectMapper.Map<List<CityDto>>(query.ToList());
        }


        /// <summary>
        /// 获取指定的地区和洲关系的数据
        /// </summary>
        /// <param name="regionCodes">地区编号集合</param>
        /// <returns></returns>
        private IDictionary<string, RegionAndContinent> GetRegionAndContinent(string[] regionCodes)
        {
            var cache = _cacheManager.GetCache("AvisAppRegionAndContinentCache");
            var dicRegionAndContinent = cache.Get("HotCity",
                f =>
                {
                    var codes = regionCodes.Distinct();
                    var query = from r in _regionRepository.GetAll()
                                join c in _continentRepository.GetAll()
                                    on r.ContinentCode equals c.Code
                                where codes.Contains(r.RegionCode)
                                orderby c.ASOrder
                                select new { r.RegionCode, c.ASCNName, c.ASOrder };

                    var dic = query.ToList().ToDictionary(r => r.RegionCode, r => new RegionAndContinent
                    {
                        RegionCode = r.RegionCode,
                        ASCNName = r.ASCNName,
                        ASOrder = r.ASOrder,
                    });

                    return dic;
                }) as Dictionary<string, RegionAndContinent>;

            return dicRegionAndContinent;
        }

        //protected IList<CityCacheItem> GetHotCityCacheItemInternal()
        //{
        //    var data = from c in _cityRepository.GetAll()
        //               where c.IsHot == true || c.IsTop == true
        //               orderby c.CusClick descending, c.CNPY
        //               select new CityCacheItem
        //               {
        //                   CNName = c.CNName,
        //                   ENName = c.ENName,
        //                   RegionCode = c.RegionCode,
        //                   CNPY = c.CNPY,
        //                   IsHot = c.IsHot,
        //               };

        //    return data.ToList();
        //}

        //protected IList<CityCacheItem> GetHotCityCacheItemInternalt()
        //{

        //    var CityData = _cityRepository.GetAll()
        //        .Where(a => (a.IsHot == true || a.IsTop == true))
        //        .OrderByDescending(c => c.ENName)
        //        .Select(c => new
        //        {

        //            c.ENName,
        //            c.CNName,
        //            c.RegionCode,
        //            c.CusClick,
        //            c.IsHot,
        //            c.IsRed,
        //            c.IsTop,
        //            c.CNPY,
        //        }).ToList();

        //    return CityData.Select(c => new CityCacheItem
        //    {
        //        ENName = c.ENName.Trim(),
        //        CNName = string.IsNullOrWhiteSpace(c.CNName) ? c.CNName.Trim() : c.CNName.Trim(),
        //        RegionCode = c.RegionCode.Trim(),
        //        IsHot = c.IsHot.HasValue ? c.IsHot.Value : false,
        //        ClickCount = c.CusClick,
        //        IsRed = c.IsRed.HasValue ? c.IsRed.Value : false,
        //        IsTop = c.IsTop.HasValue ? c.IsTop.Value : false,
        //        CNPY = c.CNPY,
        //        CNSinple = GetCNSinple(c.CNName, c.ENName),
        //        ContinentSeqNo = GetContinent(c.RegionCode).ASOrder,
        //        ContinentASCNName = GetContinent(c.RegionCode).ASCNName


        //    }).ToList();

        //}






        ///// <summary>
        ///// 获取指定RegionCode的洲信息
        ///// </summary>
        ///// <param name="RegionCode"></param>
        ///// <returns></returns>
        //protected Continent GetContinent(string RegionCode)
        //{
        //    var RegionData = _RegionManager.GetRegion(RegionCode);
        //    var ContinentData = _continentRepository.FirstOrDefault(b => b.Code == RegionData.ContinentCode);
        //    return ContinentData;
        //}

        //protected string GetCNSinple(string CNName, string ENName)
        //{
        //    var cnName = string.IsNullOrWhiteSpace(CNName) ? ENName : CNName;
        //    var CNSinple = cnName.Length > 5 ? cnName.Substring(0, 5) + "..." : cnName;
        //    return CNSinple;
        //}

        //protected string GetCNPY(string CNPY)
        //{
        //    var cnpy = string.IsNullOrEmpty(CNPY) ? "" : CNPY;
        //    return cnpy;
        //}

    }
}